﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using JsonException = System.Text.Json.JsonException;
using JsonSerializer = System.Text.Json.JsonSerializer;

namespace Elixi_AntdUi
{
   
    /// <summary>
    /// 应用程序配置模型
    /// </summary>
    public class AppConfig
    {
        private const string ConfigFileName = "config.json";
        private static AppConfig _config;
        

        private static readonly object _configLock = new object();
      

        /// <summary>
        /// 数据库配置节点
        /// </summary>
        public DatabaseConfig DatabaseConfig { get; set; }

        /// <summary>
        /// 当前用户配置节点，CurrentUser 默认不是 null
        /// </summary>
        public CurrentUser CurrentUser { get; set; }
        /// <summary>
        /// 当前其他配置节点，AllConfig 默认不是 null
        /// </summary>
        public AllConfig AllConfig { get; set; }

        /// <summary>
        /// 获取当前配置（单例模式）
        /// </summary>
        public static AppConfig Config
        {
            get
            {
                EnsureConfigLoaded(); // 使用双重检查锁定方法
                return _config;
            }
        }

        // 修改 EnsureConfigLoaded 方法
        public static void EnsureConfigLoaded()
        {
            // 双重检查锁定确保线程安全
            if (_config == null)
            {
                lock (_configLock)
                {
                    if (_config == null)
                    {
                        _config = LoadConfig(); // 这里必须赋值给 _config
                        Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                            $"config.json信息初始化");
                        Log4.Info($"System/Startup",
                            $"config.json信息初始化");

                    }
                }
            }
        }

        /// <summary>
        /// 加载配置文件（增强版）
        /// </summary>
        public static AppConfig LoadConfig_yuan(string configPath = "config.json")
        {
            try
            {
                // 检查配置文件是否存在
                if (!File.Exists(configPath))
                {
                    Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                           $"config.json信息不存在，正在生成默认配置。。。");
                    Log4.Info($"System/Startup",
                        $"config.json信息不存在，正在生成默认配置。。。");
                    // 创建默认配置文件
                    return CreateAndSaveDefaultConfig(configPath);
                }

                // 读取文件内容
                string jsonData = File.ReadAllText(configPath);

                // 配置 JSON 反序列化选项
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true,
                    ReadCommentHandling = JsonCommentHandling.Skip,
                    AllowTrailingCommas = true
                };

                // 反序列化 JSON 到对象
                var config = JsonSerializer.Deserialize<AppConfig>(jsonData, options);
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                           $"config.json信息生成成功，相对保存位置{configPath}");
                Log4.Info($"System/Startup",
                    $"config.json信息生成成功，相对保存位置{configPath}");
                // 确保配置完整性
                return EnsureConfigIntegrity(config, configPath);
            }
            catch (Exception ex)
            {
                // 记录错误并返回安全配置
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                         $"配置加载失败: {ex.Message}");
                Log4.Info($"System/Startup",
                    $"配置加载失败: {ex.Message}");
                return CreateFallbackConfig();
            }
        }
        /// <summary>
        /// 加载配置文件（修改版：先校验原始数据→报错→再执行兜底逻辑）
        /// </summary>
        public static AppConfig LoadConfig(string configPath = "config.json")
        {
            // 用于记录原始数据的错误信息，方便定位问题
            string errorMessage = string.Empty;
            AppConfig rawConfig = null; // 存储原始校验后的配置（未兜底前）

            try
            {
                #region 第一步：先校验原始数据（暴露问题，不直接修复）
                // 1. 校验1：配置文件是否存在
                if (!File.Exists(configPath))
                {
                    errorMessage = $"原始校验失败：配置文件不存在（路径：{configPath}）";
                    Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log", errorMessage);
                    Log4.Info($"System/Startup", errorMessage);
                    // 不直接修复，进入后续兜底流程
                }
                else
                {
                    // 2. 校验2：文件是否能正常读取
                    string jsonData = null;
                    try
                    {
                        jsonData = File.ReadAllText(configPath);
                    }
                    catch (Exception ex)
                    {
                        errorMessage = $"原始校验失败：配置文件读取失败（路径：{configPath}，原因：{ex.Message}）";
                        Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log", errorMessage);
                        Log4.Info($"System/Startup", errorMessage);
                        // 读取失败，进入后续兜底流程
                    }

                    if (!string.IsNullOrWhiteSpace(jsonData))
                    {
                        // 3. 校验3：JSON格式是否合法（能否反序列化）
                        var jsonOptions = new JsonSerializerOptions
                        {
                            PropertyNameCaseInsensitive = true,
                            ReadCommentHandling = JsonCommentHandling.Skip,
                            AllowTrailingCommas = true
                        };

                        try
                        {
                            rawConfig = JsonSerializer.Deserialize<AppConfig>(jsonData, jsonOptions);
                        }
                        catch (JsonException ex)
                        {
                            errorMessage = $"原始校验失败：JSON反序列化失败（路径：{configPath}，原因：{ex.Message}）";
                            Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log", errorMessage);
                            Log4.Info($"System/Startup", errorMessage);
                            // 反序列化失败，进入后续兜底流程
                        }

                        // 4. 校验4：反序列化后的配置是否完整（关键节点不缺失）
                        if (rawConfig != null)
                        {
                            bool isConfigIncomplete = false;
                            // 校验数据库配置节点
                            if (rawConfig.DatabaseConfig == null)
                            {
                                errorMessage += "；原始配置缺失DatabaseConfig节点";
                                isConfigIncomplete = true;
                            }
                            else if (string.IsNullOrWhiteSpace(rawConfig.DatabaseConfig.ConnectionString))
                            {
                                errorMessage += "；原始配置中DatabaseConfig.ConnectionString为空";
                                isConfigIncomplete = true;
                            }
                            // 校验当前用户节点
                            if (rawConfig.CurrentUser == null)
                            {
                                errorMessage += "；原始配置缺失CurrentUser节点";
                                isConfigIncomplete = true;
                            }

                            // 若配置不完整，记录错误
                            if (isConfigIncomplete)
                            {
                                // 补充错误前缀（避免空字符串拼接）
                                if (string.IsNullOrWhiteSpace(errorMessage))
                                    errorMessage = $"原始校验失败：配置节点不完整（路径：{configPath}）";
                                else
                                    errorMessage = $"原始校验失败：配置节点不完整（路径：{configPath}）{errorMessage}";

                                Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log", errorMessage);
                                Log4.Info($"System/Startup", errorMessage);
                            }
                        }
                    }
                }
                #endregion

                #region 第二步：根据校验结果执行兜底逻辑（修复/生成配置）
                // 场景1：原始校验完全通过（文件存在+读取成功+反序列化正常+配置完整）
                if (rawConfig != null && string.IsNullOrWhiteSpace(errorMessage))
                {
                    Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log",
                        $"配置校验通过，直接使用原始配置（路径：{configPath}）");
                    Log4.Info($"System/Startup",
                        $"配置校验通过，直接使用原始配置（路径：{configPath}）");
                    return rawConfig;
                }

                // 场景2：原始校验失败，执行兜底逻辑（复用原有修复逻辑）
                Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log",
                    $"开始执行兜底逻辑，修复/生成配置（原错误：{errorMessage}）");
                Log4.Info($"System/Startup",
                    $"开始执行兜底逻辑，修复/生成配置（原错误：{errorMessage}）");

                // 子场景1：文件不存在 → 生成默认配置并保存
                if (!File.Exists(configPath))
                {
                    Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log",
                        "兜底逻辑：配置文件不存在，生成默认配置");
                    Log4.Info($"System/Startup",
                        "兜底逻辑：配置文件不存在，生成默认配置");
                    return CreateAndSaveDefaultConfig(configPath);
                }

                // 子场景2：文件存在但读取/反序列化失败 → 返回应急配置（不覆盖原文件，避免破坏原始数据）
                if (rawConfig == null)
                {
                    Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log",
                        "兜底逻辑：配置读取/反序列化失败，使用应急配置（不修改原文件）");
                    Log4.Info($"System/Startup",
                        "兜底逻辑：配置读取/反序列化失败，使用应急配置（不修改原文件）");
                    return CreateFallbackConfig();
                }

                // 子场景3：配置不完整 → 补全配置并保存（修复后返回）
                if (rawConfig != null && !string.IsNullOrWhiteSpace(errorMessage))
                {
                    Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log",
                        "兜底逻辑：配置节点不完整，补全后保存");
                    Log4.Info($"System/Startup",
                        "兜底逻辑：配置节点不完整，补全后保存");
                    var fixedConfig = EnsureConfigIntegrity(rawConfig, configPath);
                    SaveConfig(fixedConfig, configPath); // 保存修复后的配置
                    return fixedConfig;
                }

                // 最终兜底：若以上场景都覆盖不到，返回应急配置
                Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log",
                    "兜底逻辑：未知错误，返回应急配置");
                Log4.Info($"System/Startup",
                    "兜底逻辑：未知错误，返回应急配置");
                return CreateFallbackConfig();
                #endregion
            }
            catch (Exception ex)
            {
                // 捕获兜底过程中的异常（避免兜底逻辑本身出错导致程序崩溃）
                string finalError = $"兜底逻辑执行失败：{ex.Message}（原校验错误：{errorMessage}）";
                Log4.Info($"Log4/Sqllog/{DateTime.Today:yyyy-MM-dd}.log", finalError);
                Log4.Info($"System/Startup", finalError);
                return CreateFallbackConfig();
            }
        }
        /// <summary>
        /// 创建并保存默认配置
        /// </summary>
        private static AppConfig CreateAndSaveDefaultConfig(string configPath)
        {
            try
            {
                var defaultConfig = new AppConfig
                {
                    DatabaseConfig = new DatabaseConfig
                    {
                        DbType = "SqlServer",
                        ConnectionString = "Server=.;Database=DefaultDB;Trusted_Connection=True;",
                        IsAutoCloseConnection = "true"
                    },
                    CurrentUser = new CurrentUser
                    {
                        UserName = "",
                        UserGuid = "",
                        UserPassword = ""
                    },
                    AllConfig = new AllConfig
                    {
                        IsHFReader = 1,
                        Isadmin = 1,
                        IsInOrOut=0,
                        VideoMaxFPS = 30,
                        VideoMinFPS = 10,
                    }
                };

                // 保存默认配置
                SaveConfig(defaultConfig, configPath);
                
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                          $"config.json信息生成成功，相对保存位置{configPath}");
                Log4.Info($"System/Startup",
                    $"config.json信息生成成功，相对保存位置{configPath}");
                return defaultConfig;
            }
            catch (Exception ex)
            {
                 
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                        $"创建默认配置失败: {ex.Message}");
                Log4.Info($"System/Startup",
                    $"创建默认配置失败: {ex.Message}");
                return CreateFallbackConfig();
            }
        }

        /// <summary>
        /// 确保配置完整性
        /// </summary>
        private static AppConfig EnsureConfigIntegrity(AppConfig config, string sourcePath)
        {
            if (config == null)
            {
                
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                          $"反序列化配置为空，使用默认配置");
                Log4.Info($"System/Startup",
                    $"反序列化配置为空，使用默认配置");
                return CreateAndSaveDefaultConfig(sourcePath);
            }

            // 确保关键组件不为空
           
            if(config.DatabaseConfig is    null)
                config.DatabaseConfig =  new DatabaseConfig();
          
            if (config.CurrentUser is null)
                config.CurrentUser = new CurrentUser();
            // 验证必要属性
            if (string.IsNullOrWhiteSpace(config.DatabaseConfig.ConnectionString))
            {
                config.DatabaseConfig.ConnectionString = "Server=.;Database=DefaultDB;Trusted_Connection=True;";
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                       $"数据库连接字符串为空，使用默认值:{config.DatabaseConfig.ConnectionString}");
                Log4.Info($"System/Startup",
                    $"数据库连接字符串为空，使用默认值:{config.DatabaseConfig.ConnectionString}");
                
            }

            return config;
        }

        /// <summary>
        /// 创建安全回退配置
        /// </summary>
        private static AppConfig CreateFallbackConfig()
        {
            return new AppConfig
            {
                DatabaseConfig = new DatabaseConfig
                {
                    DbType = "SqlServer",
                    ConnectionString = "Server=.;Database=EmergencyDB;Trusted_Connection=True;",
                    IsAutoCloseConnection = "true"
                },
                CurrentUser = new CurrentUser
                {
                    UserName = "",
                    UserGuid = "",
                    UserPassword = "",
                },
                AllConfig = new AllConfig
                {
                    IsHFReader = 1,
                    Isadmin = 1,
                    IsInOrOut = 0,
                    VideoMaxFPS = 30,
                    VideoMinFPS = 10,
                }
            };
        }

        /// <summary>
        /// 保存配置（优化版）
        /// </summary>
        public static void SaveConfig(AppConfig config, string configPath = "config.json")
        {
            try
            {
                // 确保配置完整
                config = EnsureConfigIntegrity(config, configPath);

                var options = new JsonSerializerOptions
                {
                    WriteIndented = true,
                    PropertyNamingPolicy = null
                };

                string json = JsonSerializer.Serialize(config, options);
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                    $"config信息已更新!\n用户名: {config.CurrentUser.UserName}\n主键: {config.CurrentUser.UserGuid}");
                Log4.Info($"System/Startup",
                    $"config信息已更新!\n用户名: {config.CurrentUser.UserName}\n主键: {config.CurrentUser.UserGuid}");
                File.WriteAllText(configPath, json);
                
                // 更新单例实例
                _config = config;
                 
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                   $"配置保存成功: {configPath}");
                Log4.Info($"System/Startup",
                    $"配置保存成功: {configPath}");

            }
            catch (Exception ex)
            {
                
                Log4.Info($"Log4/Sqllog/{DateTime.Today.ToString("yyyy-MM-dd")}.log",
                  $"保存配置失败: {ex.Message}");
                Log4.Info($"System/Startup",
                    $"保存配置失败: {ex.Message}");

            }
        }

        /// <summary>
        /// 更新当前用户信息
        /// </summary>
        public static void UpdateCurrentUser(string userName, string userGuid)
        {
            EnsureConfigLoaded();

            // 确保当前用户对象已初始化
            if (Config.CurrentUser == null)
            {
                Config.CurrentUser = new CurrentUser();
            }

            // 更新用户信息
            Config.CurrentUser.UserName = userName;
            Config.CurrentUser.UserGuid = userGuid;
            // 保存配置
            SaveConfig(Config);
        }
        /// <summary>
        /// 更新当前用户信息
        /// </summary>
        public static void UpdateCurrentUser(string userName, string userGuid, string userpassword)
        {
            EnsureConfigLoaded();

            // 确保当前用户对象已初始化
            if (Config.CurrentUser == null)
            {
                Config.CurrentUser = new CurrentUser();
            }

            // 更新用户信息
            Config.CurrentUser.UserName = userName;
            Config.CurrentUser.UserGuid = userGuid;
            Config.CurrentUser.UserPassword =  userpassword;
            // 保存配置
            SaveConfig(Config);
        }


        /// <summary>
        /// 计算字符串的MD5加密结果（32位小写）
        /// </summary>
        /// <param name="input">待加密的字符串</param>
        /// <returns>MD5加密后的32位十六进制字符串</returns>
        public static string Md5Encrypt(string input)
        {
            // 处理空输入（视为空字符串）
            input ??= string.Empty;

            // 创建MD5实例
            using (MD5 md5 = MD5.Create())
            {
                // 1. 将字符串转为UTF8字节数组
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);

                // 2. 计算MD5哈希值（得到16字节的哈希结果）
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                // 3. 将哈希字节数组转为32位十六进制字符串
                StringBuilder sb = new StringBuilder();
                foreach (byte b in hashBytes)
                {
                    // 每个字节转为2位十六进制（x2表示小写，X2表示大写）
                    sb.Append(b.ToString("x2"));
                }
                return sb.ToString();
            }
        }

    }





    /// <summary>
    /// 数据库配置
    /// </summary>
    public class DatabaseConfig
    {
        /// <summary>
        /// 数据库类型 (SqlServer, MySql, Oracle, PostgreSQL)
        /// </summary>
        public string DbType { get; set; }  
        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        public string ConnectionString { get; set; }  
        public string IsAutoCloseConnection { get; set; }  
    }

    /// <summary>
    /// 当前用户信息
    /// </summary>
    public class CurrentUser
    {
        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName { get; set; } 

        /// <summary>
        /// 用户全局唯一标识
        /// </summary>
        public string UserGuid { get; set; }
        /// <summary>
        /// 用户密码
        /// </summary>
        public string UserPassword { get; set; }
    }
    /// <summary>
    /// 其他类
    /// </summary>
    public class AllConfig
    {
        /// <summary>
        /// 用户名
        /// </summary>
        public int IsHFReader { get; set; } // 可选值: 0:不展示调用按钮 1:展示调用按钮
        public int Isadmin { get; set; } // 可选值: 0:不展示调用按钮 1:展示调用按钮
        public int IsInOrOut { get; set; } // 可选值: 0:入库操作界面 1:出库操作界面
        public int IsAutoInfor_Click { get; set; } // 可选值: 0:不自动执行校验 1:自动执行校验
        public int IsAutobtn_save { get; set; } // 可选值: 0:不自动执行保存数据 1:自动执行保存数据
        public int VideoMaxFPS { get; set; } // 可选值: 无限大 ,视频帧率。
        public int VideoMinFPS { get; set; } // 可选值: 1,最小不要超过 ,视频帧率。

    }
}
